use anyhow::Result;
use rusqlite::Connection;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn main() -> Result<()> {
    let conn = Connection::open("./newpipe.db")?;
    std::fs::create_dir("./playlists")?;

    let sqlite_playlists = get_sqlite_playlists(&conn)?;
    for sqlite_playlist in sqlite_playlists {
        let name = sqlite_playlist.name;
        let path = PathBuf::from(&format!("./playlists/{}.txt", name));
        let mut file = File::create(path)?;
        println!("Parsing local playlist: {}", name);
        let streams = get_playlist_streams(&conn, sqlite_playlist.uid)?;
        for stream in streams {
            let link = get_stream(&conn, stream.stream_id)?;
            file.write_all(format!("{}\n", link).as_bytes())?;
        }
    }
    Ok(())
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PlaylistSqlite {
    pub uid: i32,
    pub name: String,
}
pub struct PlaylistStreamJoin {
    stream_id: i32,
    join_index: i32,
}
pub fn get_sqlite_playlists(conn: &Connection) -> Result<Vec<PlaylistSqlite>> {
    let mut stmt = conn.prepare("SELECT uid, name FROM playlists")?;
    let mut playlists = Vec::new();
    let playlist_iter = stmt.query_map([], |row| {
        Ok(PlaylistSqlite {
            uid: row.get(0)?,
            name: row.get(1)?,
        })
    })?;
    for playlist in playlist_iter {
        playlists.push(playlist.unwrap());
    }
    println!("{:#?}", playlists);
    Ok(playlists)
}
pub fn get_playlist_streams(
    conn: &Connection,
    playlist_id: i32,
) -> Result<Vec<PlaylistStreamJoin>> {
    let mut stmt = conn.prepare(&format!(
        "SELECT stream_id, join_index FROM playlist_stream_join WHERE playlist_id = {}",
        playlist_id
    ))?;
    let mut playlist_streams = Vec::new();
    let playlist_streams_iter = stmt.query_map([], |row| {
        Ok(PlaylistStreamJoin {
            stream_id: row.get(0)?,
            join_index: row.get(1)?,
        })
    })?;
    for playlist_stream in playlist_streams_iter {
        playlist_streams.push(playlist_stream.unwrap());
    }
    playlist_streams.sort_by(|a, b| b.join_index.cmp(&a.join_index));
    Ok(playlist_streams)
}
pub fn get_stream(conn: &Connection, stream: i32) -> Result<String> {
    let mut stmt = conn.prepare(&format!("SELECT url FROM streams WHERE uid = {}", stream))?;
    let url: String = stmt
        .query_map([], |row| row.get(0))?
        .next()
        .unwrap()
        .unwrap();
    Ok(url)
}
